package com.duobaoyu.dby.supply.biz.strategy.message.order.logistics;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.duobaoyu.dby.channel.adapter.enums.BizMessageTypeEnum;
import com.duobaoyu.dby.channel.adapter.enums.ChannelCodeEnum;
import com.duobaoyu.dby.channel.adapter.enums.biz.order.OrderStatusEnum;
import com.duobaoyu.dby.channel.strategy.supply.impl.real.ordering.callback.OrderingOrderTrackCallback;
import com.duobaoyu.dby.supply.biz.constant.OperateSourceConstants;
import com.duobaoyu.dby.supply.biz.constant.OrderOperateConstants;
import com.duobaoyu.dby.supply.biz.service.order.OrderService;
import com.duobaoyu.dby.supply.biz.strategy.message.order.base.BaseOrderAsyncHandler;
import com.duobaoyu.dby.supply.common.biz.bo.message.ChannelMessageBO;
import com.duobaoyu.dby.supply.db.entity.order.Order;
import com.duobaoyu.dby.supply.db.entity.order.OrderLogistics;
import com.duobaoyu.dby.supply.db.repository.order.OrderLogisticsRepository;
import com.duobaoyu.dby.supply.db.repository.order.OrderRepository;
import com.google.common.collect.Sets;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Component;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author 001
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class OrderingLogisticsChangeAsyncHandler extends BaseOrderAsyncHandler {

	private final OrderService orderService;
	private final OrderRepository orderRepository;
	private final TransactionTemplate transactionTemplate;
	private final OrderLogisticsRepository orderLogisticsRepository;

	@Override
	protected Set<String> channelCodes() {
		return Sets.newHashSet(ChannelCodeEnum.ORDERING.getValue());
	}

	@Override
	protected Set<Integer> bizMessageTypes() {
		return Sets.newHashSet(BizMessageTypeEnum.LOGISTICS_STATUS_CHANGE.getValue());
	}

	@Override
	protected Boolean executeHandler(ChannelMessageBO channelMessage, Object beforeResult) {
		OrderingOrderTrackCallback orderingOrderTrackCallback = JSON.parseObject(channelMessage.getOriginalMessage(), OrderingOrderTrackCallback.class);
		List<String> channelOrderSnList = orderingOrderTrackCallback.getPkgDataList().stream().map(OrderingOrderTrackCallback.PkgData::getPkgNo).collect(Collectors.toList());

		if(CollectionUtils.isEmpty(channelOrderSnList)){
			log.info("message:{},channelCode:{},data:{}","物流回调失败",channelMessage.getChannelCode(),JSON.toJSONString(channelMessage));
			return Boolean.FALSE;
		}
		List<Order> orderList = orderRepository.getBaseMapper().selectList(Wrappers.<Order>lambdaQuery().in(Order::getChannelOrderSn, channelOrderSnList));
		if(CollectionUtils.isEmpty(orderList)){
			return Boolean.FALSE;
		}

		List<OrderLogistics> logistics = new ArrayList<>();
		for (OrderingOrderTrackCallback.PkgData pkgData:orderingOrderTrackCallback.getPkgDataList()) {
			for (Order order:orderList) {
				if(pkgData.getPkgNo().equals(order.getChannelOrderSn())){
					for (OrderingOrderTrackCallback.PkgData.ExpressData expressData:pkgData.getExpressDataList()) {
						OrderLogistics orderLogistics = new OrderLogistics();
						orderLogistics.setDeliveryOrderSn(expressData.getExpressNum());
						orderLogistics.setDeliveryCarrier(expressData.getExpressCompany());
						orderLogistics.setPackageId(pkgData.getPkgNo());
						orderLogistics.setOrderSn(order.getOrderSn());
						logistics.add(orderLogistics);
					}
				}
			}
		}

		transactionTemplate.execute(new TransactionCallbackWithoutResult() {
			@Override
			protected void doInTransactionWithoutResult(@NotNull TransactionStatus transactionStatus) {
				List<String> orderSnList = orderList.stream().map(Order::getOrderSn).collect(Collectors.toList());
				orderService.updateStatusByOrderSnList(orderSnList, OrderStatusEnum.SHIPPED, OrderStatusEnum.WAIT_SHIP, OperateSourceConstants.OPERATION_CHANNEL, OrderOperateConstants.CHANNEL_ORDER_SHIPMENT,null);
				orderLogisticsRepository.saveBatch(logistics);
			}
		});
		return Boolean.TRUE;
	}
}
